#include <iostream>
#include <string>
#include <sqlite3.h>
#include <vector>
// 封装实现SqliteHelper类，提供sqlite数据库操作接口，完成数据基础增删查改
// 1. 创建打开数据库文件
// 2. 对数据库进行操作
//      2.1 表的打开
//      2.2 数据的操作
// 3. 关闭数据库

/*****************************************************************************
* 
*   SQLITE_OPEN_READWRITE -- 以可读可写⽅式打开数据库⽂件
*   SQLITE_OPEN_CREATE -- 不存在数据库⽂件则创建
*   SQLITE_OPEN_NOMUTEX--多线程模式，只要不同的线程使⽤不同的连接即可保证线程安全
*   SQLITE_OPEN_FULLMUTEX--串⾏化模式
*   SQLITE_OK 表⽰成功
*
*****************************************************************************/
class SqliteHelper
{
public:
    typedef int(*SqliteCallback)(void*,int,char**,char**);
    SqliteHelper(const std::string dbfile)
        :_dbfile(dbfile)
        ,_handler(nullptr)
    {}
    bool open(int safe_level = SQLITE_OPEN_FULLMUTEX)
    {
        // 文件名, 句柄, 安全等级加打开方式, nullptr
        // int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
        int ret = sqlite3_open_v2(_dbfile.c_str(), &_handler, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | safe_level, nullptr);
        if(ret != SQLITE_OK)
        {
            std::cout << "创建/打开数据库文件失败";
            std::cout << sqlite3_errmsg(_handler) << std::endl;
            return false;
        }
        return true;
    }
    bool exec(const std::string &sql, SqliteCallback cb, void* arg)
    {
        // 句柄, SQL语句, 回调函数, 传递参数, 错误值
        // int sqlite3_exec(sqlite3*, char *sql, int (*callback)(void*,int,char**,char**), void* arg, char **err));
        int ret = sqlite3_exec(_handler, sql.c_str(), cb, arg, nullptr);
        if(ret != SQLITE_OK)
        {
            std::cout << sql << std::endl;
            std::cout << "执行语句失败";
            std::cout << sqlite3_errmsg(_handler);
            return false;
        }
        return true;
    }
    void close()
    {
        // int sqlite3_close_v2(sqlite3*);
        if(_handler)
        {
            sqlite3_close_v2(_handler);
        }
    }
private:
    std::string _dbfile;
    sqlite3 *_handler;
};